For future reference:
Web Database Applications with PHP and MySQL, 2nd Edition [electronic resource]
[Any VTC student may refer to this book; might help in Spring]

Basic Shopping Cart

Idea of a shopping cart with javascript
https://code-boxx.com/simple-vanilla-javascript-shopping-cart/
QUICK NOTES
For you guys who just want to use this as a “plugin”:
•	Edit products.js, fill in your own products.
•	Put the product images in the images/ folder.
•	Set iURL in cart.js section A to an absolute URL if you have trouble with the images.
•	Launch cart.html, use http:// not file://.
•	Lastly, complete your own checkout sequence cart.js, section H.
But code-boxx does not do payment.

Discussion of how to do credit cards:
https://sitebeginner.com/money/acceptcreditcards/
https://www.websitespot.com/blog/how-to-make-a-website-that-accepts-credit-cards/

https://top-merchantservices.com/
Nowadays, however, apps like Venmo and PayPal let you send and receive money from your phone or computer with ease
https://venmo.com/
PAYPAL
https://www.wikihow.com/Use-PayPal-to-Accept-Credit-Card-Payments
https://www.wikihow.com/Use-PayPal-to-Accept-Credit-Card-Payments#Using-PayPal-Checkout-on-the-Web

How to do secure payments:
https://www.ecwid.com/blog/https-and-ssl.html
(Done by a commercial company, but has good info)

How to become a certificate authority:
https://www.thesslstore.com/blog/how-to-become-a-certificate-authority/

How to accept checks for payment:
https://echeckdirect.com/index.html

There will probably not be a LAB for shopping cart, but you need to be familiar with the concepts.

More of the basic shopping cart:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
LICENSE
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

Copyright by Code Boxx

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
MORE
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Please visit https://code-boxx.com/ for more!

/* (A) ENTIRE PAGE */
#cart-wrap * {
  font-family: arial, sans-serif;
  box-sizing: border-box;
}
#cart-wrap {
  display: flex;
  margin: 0 auto;
  max-width: 1200px;
}
#cart-products, #cart-items { padding: 10px; }
#cart-products { flex-grow: 1; }
#cart-items { width: 180px; }
input.cart, button.cart {
  padding: 10px;
  border: 0;
  background: #ff4316;
  color: #fff;
  font-weight: 700;
  cursor: pointer;
}

/* (B) PRODUCTS LIST */
#cart-products {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-gap: 10px;
}
.p-item {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
  text-align: center;
}
.p-img { max-width: 150px; }
.p-name, .p-price { font-weight: 700; }
.p-name, .p-desc, .p-price { margin: 5px 0; }
.p-name {
  font-size: 1.35em;
  text-transform: uppercase;
}
.p-desc {
  color: #7c7979;
  font-size: 0.9em;
}
.p-price { color: #e13d16; }
.p-add { width: 100%; }

/* (C) CURRENT SHOPPING CART */
#cart-items {
  background: #31394d;
  color: #fff;
  border-radius: 5px;
}
.c-item {
  padding: 10px 0;
  display: flex;
  flex-wrap: wrap;
}
.c-name, .c-total {
  font-size: 1.05em;
  font-weight: 700;
}
.c-name, .c-total, button.c-empty, button.c-checkout { width: 100%; }
.c-total, button.c-empty, button.c-checkout { margin-top: 10px; }
.c-del { width: 25%; }
.c-qty { width: 75%; }
.c-empty, .c-checkout { width: 100%; }

/* (D) RESPONSIVE */
@media screen and (max-width: 640px) {
  #cart-products {
    grid-template-columns: 100%;
  }
}

<!DOCTYPE html>
<html>
  <head>
    <title>Simple JS Cart</title>
    <link rel="stylesheet" href="cart.css">
    <script src="products.js"></script>
    <script src="cart.js"></script>
  </head>
  <body>
    <!-- (A) CART -->
    <div id="cart-wrap">
      <!-- (A1) PRODUCTS LIST -->
      <div id="cart-products"></div>

      <!-- (A2) CURRENT CART ITEMS -->
      <div id="cart-items"></div>
    </div>

    <!-- (B) TEMPLATES -->
    <!-- (B1) PRODUCT CELL -->
    <template id="template-product">
    <div class="p-item">
      <img class="p-img"/>
      <div class="p-name"></div>
      <div class="p-desc"></div>
      <div class="p-price"></div>
      <button class="cart p-add">Add To Cart</button>
    </div>
    </template>

    <!-- (B2) CART ITEMS -->
    <template id="template-cart">
    <div class="c-item">
      <div class="c-name"></div>
      <button class="c-del cart">X</button>
      <input class="c-qty" type="number" min="0"/>
    </div>
    </template>
    <template id="template-cart-checkout">
      <button class="c-empty cart" onclick="cart.nuke()">Empty</button>
      <button class="c-checkout cart" onclick="cart.checkout()">Checkout</button>
    </template>
  </body>
</html>

var cart = {
  // (A) PROPERTIES
  hPdt : null,      // html products list
  hItems : null,    // html current cart
  items : {},       // current items in cart
  iURL : "images/", // product image url folder

  // (B) LOCALSTORAGE CART
  // (B1) SAVE CURRENT CART INTO LOCALSTORAGE
  save : () => {
    localStorage.setItem("cart", JSON.stringify(cart.items));
  },

  // (B2) LOAD CART FROM LOCALSTORAGE
  load : () => {
    cart.items = localStorage.getItem("cart");
    if (cart.items == null) { cart.items = {}; }
    else { cart.items = JSON.parse(cart.items); }
  },

  // (B3) EMPTY ENTIRE CART
  nuke : () => { if (confirm("Empty cart?")) {
    cart.items = {};
    localStorage.removeItem("cart");
    cart.list();
  }},

  // (C) INITIALIZE
  init : () => {
    // (C1) GET HTML ELEMENTS
    cart.hPdt = document.getElementById("cart-products");
    cart.hItems = document.getElementById("cart-items");

    // (C2) DRAW PRODUCTS LIST
    cart.hPdt.innerHTML = "";
    let template = document.getElementById("template-product").content,
        p, item, part;
    for (let id in products) {
      p = products[id];
      item = template.cloneNode(true);
      item.querySelector(".p-img").src = cart.iURL + p.img;
      item.querySelector(".p-name").textContent = p.name;
      item.querySelector(".p-desc").textContent = p.desc;
      item.querySelector(".p-price").textContent = "$" + p.price.toFixed(2);
      item.querySelector(".p-add").onclick = () => { cart.add(id); };
      cart.hPdt.appendChild(item);
    }

    // (C3) LOAD CART FROM PREVIOUS SESSION
    cart.load();

    // (C4) LIST CURRENT CART ITEMS
    cart.list();
  },

  // (D) LIST CURRENT CART ITEMS (IN HTML)
  list : () => {
    // (D1) RESET
    cart.hItems.innerHTML = "";
    let item, part, pdt, empty = true;
    for (let key in cart.items) {
      if (cart.items.hasOwnProperty(key)) { empty = false; break; }
    }

    // (D2) CART IS EMPTY
    if (empty) {
      item = document.createElement("div");
      item.innerHTML = "Cart is empty";
      cart.hItems.appendChild(item);
    }

    // (D3) CART IS NOT EMPTY - LIST ITEMS
    else {
      let template = document.getElementById("template-cart").content,
          p, total = 0, subtotal = 0;
      for (let id in cart.items) {
        // (D3-1) PRODUCT ITEM
        p = products[id];
        item = template.cloneNode(true);
        item.querySelector(".c-del").onclick = () => { cart.remove(id); };
        item.querySelector(".c-name").textContent = p.name;
        item.querySelector(".c-qty").value = cart.items[id];
        item.querySelector(".c-qty").onchange = function () { cart.change(id, this.value); };
        cart.hItems.appendChild(item);

        // (D3-2) SUBTOTAL
        subtotal = cart.items[id] * p.price;
        total += subtotal;
      }

      // (D3-3) TOTAL AMOUNT
      item = document.createElement("div");
      item.className = "c-total";
      item.id = "c-total";
      item.innerHTML ="TOTAL: $" + total;
      cart.hItems.appendChild(item);

      // (D3-4) EMPTY & CHECKOUT
      item = document.getElementById("template-cart-checkout").content.cloneNode(true);
      cart.hItems.appendChild(item);
    }
  },

  // (E) ADD ITEM INTO CART
  add : (id) => {
    if (cart.items[id] == undefined) { cart.items[id] = 1; }
    else { cart.items[id]++; }
    cart.save(); cart.list();
  },

  // (F) CHANGE QUANTITY
  change : (pid, qty) => {
    // (F1) REMOVE ITEM
    if (qty <= 0) {
      delete cart.items[pid];
      cart.save(); cart.list();
    }

    // (F2) UPDATE TOTAL ONLY
    else {
      cart.items[pid] = qty;
      var total = 0;
      for (let id in cart.items) {
        total += cart.items[id] * products[id].price;
        document.getElementById("c-total").innerHTML ="TOTAL: $" + total;
      }
    }
  },

  // (G) REMOVE ITEM FROM CART
  remove : (id) => {
    delete cart.items[id];
    cart.save();
    cart.list();
  },

  // (H) CHECKOUT
  checkout : () => {
    // SEND DATA TO SERVER
    // CHECKS
    // SEND AN EMAIL
    // RECORD TO DATABASE
    // PAYMENT
    // WHATEVER IS REQUIRED
    alert("TO DO");

    /*
    var data = new FormData();
    data.append("cart", JSON.stringify(cart.items));
    data.append("products", JSON.stringify(products));

    fetch("SERVER-SCRIPT", { method:"POST", body:data })
    .then(res=>res.text()).then((res) => {
      console.log(res);
    })
    .catch((err) => { console.error(err); });
    */
  }
};
window.addEventListener("DOMContentLoaded", cart.init);

// DUMMY PRODUCTS (PRODUCT ID : DATA)
var products = {
  123: {
    name : "MokBook Thicc",
    desc : "Greatest properly off ham exercise all.",
    img : "dummy-pdt-b.jpg",
    price : 2034
  },
  124: {
    name : "MokBook Rookie",
    desc : "Unsatiable its possession nor off.",
    img : "dummy-pdt-b.jpg",
    price : 1247
  },
  125: {
    name : "iPong Max",
    desc : "All difficulty unreserved the solicitude.",
    img : "dummy-pdt-a.jpg",
    price : 675
  },
  126: {
    name : "iTab Pok",
    desc : "Had judgment out property the supplied. ",
    img : "dummy-pdt-a.jpg",
    price : 842
  }
};

Folder images contains pictures of your products.